home *** CD-ROM | disk | FTP | other *** search
- /*
- File: SampleShim.c
-
-
- Version: 1.1
-
- Copyright: © 1998-1999 by Apple Computer, Inc., all rights reserved.
-
- */
-
- /*
- MacOS Headers
- */
- #include <CodeFragments.h>
- #include <Devices.h>
- #include <DriverServices.h>
- #include <MacTypes.h>
- #include <Processes.h>
- #include <Resources.h>
- #include <String.h>
- #include <TextUtils.h>
- #include <Errors.h>
- #include <Memory.h>
- #include <USB.h>
-
- /*
- Driver Headers
- */
- #include "SampleDriverVersion.h"
- #include "SampleShim.h"
-
- #define kUSBInterfaceType 'usbi'
- #define kUSBDeviceType 'usbd'
- #define kDispatchTableAddress "DispatchTableAddr"
-
- /*
- Global variables used by the Shim
- */
- static Boolean shimInFile;
- static FSSpec shimFSSpec;
- static TimerID gGiveTimeTimer = nil;
- static DriverRefNum gNewDrvrRef = 0;
- static USBDeviceNotificationParameterBlock gpb;
- static Boolean gNotifierInstalledFlag = false;
-
-
- OSErr CFragInitRoutine(CFragInitBlockPtr initBlkPtr);
- OSStatus USBShim(void);
- OSStatus FindMatchingRegEntryForUSBRef (USBDeviceRef ref, ResType theType, RegEntryID *resultID);
-
-
- /*
- Exported Functions for the Code Fragment Manager
- */
- // This routine gets called by the Code Fragment Manager when the shim's code fragment is loaded
- OSErr CFragInitRoutine(CFragInitBlockPtr initBlkPtr)
- {
- shimInFile = false;
-
- if (CFragHasFileLocation(initBlkPtr->fragLocator.where))
- {
- shimInFile = true;
- shimFSSpec = *(initBlkPtr->fragLocator.u.onDisk.fileSpec); // save the FSSpec, in case we need it later
- }
- return noErr;
- }
-
-
- /*
- Functions Exported for the USB Expert
- */
- // This routine is exported for use by the USB Expert to initialize the shim when
- // the expert loads it
- OSStatus USBShim(void)
- {
- OSStatus status = noErr;
-
- // Setup notification for Vendor Specific Devices
- gpb.usbDeviceNotification = kNotifyAnyEvent; // tell me about everything
- gpb.usbClass = kUSBAnyClass;
- gpb.usbSubClass = kUSBAnySubClass;
- gpb.usbProtocol = kUSBAnyProtocol;
- gpb.usbVendor = 0x0547; // Notify me of my specific Vendor ID
- gpb.usbProduct = 0x1002; // Notify me of my specific Product ID
- gpb.result = noErr;
- gpb.callback = (USBDeviceNotificationCallbackProcPtr) &myNotificationCallback;
- gpb.refcon = nil;
- USBInstallDeviceNotification (&gpb);
- gNotifierInstalledFlag = true; // keep track of whether notifier routine was installed
-
- return status;
- }
-
- // This routine is exported for use by the USB Expert to terminate the shim before it gets removed
- void USBShimTermination(void)
- {
- // check if notifier was installed
- if (gNotifierInstalledFlag == true)
- {
- // Remove the device notofication
- USBRemoveDeviceNotification(gpb.token);
- }
- }
-
- // This function is passed to the USB Expert for device add/remove notification
- void myNotificationCallback(USBDeviceNotificationParameterBlock *pb)
- {
- CFragConnectionID connID;
- CFragSymbolClass symClass;
- RegEntryID regEntry;
- OSStatus err;
- THz saveZone;
- Ptr dispatchArrayPtr;
-
-
- switch(pb->usbDeviceNotification) // why were we notified?
- {
- case kNotifyAddDevice: // because mass storage device appeared
- case kNotifyAddInterface: // because mass storage interface appeared
- {
- USBExpertStatus(pb->usbDeviceRef, "\pdevice/interface added", 0);
- // the device or interface attachment has been detected
- // first find the CFragConnectionID associated with this USBDeviceRef
- err = USBGetDriverConnectionID(&pb->usbDeviceRef, &connID);
- if (err == noErr)
- {
- // find the matching RegEntryID for the device
- err = FindMatchingRegEntryForUSBRef(pb->usbDeviceRef, kUSBDeviceType, ®Entry);
- if (err == noErr)
- {
-
- saveZone = GetZone(); // save the current zone
- SetZone(SystemZone()); // set the current zone to the System zone
- // otherwise the FindSymbol call will fail to find the dispatch table symbol
-
- USBExpertStatus(pb->usbDeviceRef, "\pDevice found", 0);
-
- SetZone(saveZone);
-
- }
- else
- {
- USBExpertStatus(pb->usbDeviceRef, "\pmyNotificationCallback: error calling FindMatchingRegEntryForUSBRef", err);
- }
- }
- else
- {
- USBExpertStatus(pb->usbDeviceRef, "\pmyNotificationCallback: error calling USBGetDriverConnectionID", err);
- }
- }
- break;
-
- case kNotifyRemoveDevice: // because a mass storage device or interface disappeared
- case kNotifyRemoveInterface: // because a mass storage device or interface disappeared
- {
- USBExpertStatus(pb->usbDeviceRef, "\pdevice/interface removed", 0);
- }
- break;
-
- default:
- break;
- }
- }
-
- /*
- OSStatus FindMatchingRegEntryForUSBRef (USBDeviceRef ref, ResType theType, RegEntryID *theEntry)
- takes the USBDeviceRef and searches the name registry for the registered entry based on theType
- If the USBDeviceRef is found, then the corresponding RegEntryID is returned.
- for theType parameter pass in 'usbd' for a USB Device or
- 'usbi' for a USB Interface
-
- */
- OSStatus FindMatchingRegEntryForUSBRef (USBDeviceRef ref, ResType theType, RegEntryID *theEntry)
- {
- OSStatus err = noErr;
- OSStatus status;
- RegEntryIter cookie;
- unsigned char usbNodeStr[32] = "\pAAPL,USBNodeType";
- RegCStrEntryNamePtr usbNodeCStr = p2cstr(usbNodeStr);
- unsigned char usbInterfaceRefStr[32] = "\pinterfaceRef";
- unsigned char usbDeviceRefStr[32] = "\pdeviceRef";
- RegCStrEntryNamePtr usbRefCStr;
- RegEntryIterationOp iterOp;
- ResType usbNodeType;
- RegPropertyValueSize theSize;
- USBDeviceRef tempRef;
- Boolean done = false;
- Boolean found = false;
-
- if ((theType != kUSBInterfaceType) && (theType != kUSBDeviceType))
- return -1; // if the desired type is not 'usbd' nor 'usbi' then return a generic error
-
- err = RegistryEntryIDInit( theEntry );
- if (err != noErr)
- {
- USBExpertStatus(ref, "\pFindMatchingRegEntryForUSBRef: RegistryEntryIDInit failed", err);
- return err;
- }
-
- err = RegistryEntryIterateCreate( &cookie );
- if (err != noErr)
- {
- USBExpertStatus(ref, "\pFindMatchingRegEntryForUSBRef: RegistryEntryIterateCreate failed", err);
- return err;
- }
-
- iterOp = kRegIterDescendants;
-
- err = RegistryEntrySearch( &cookie, iterOp, theEntry, &done,
- usbNodeCStr, nil, 0);
-
- // set up the usbRefCStr so that we will search for either the interfaceRef or deviceRef
- // property
- if (theType == kUSBInterfaceType)
- usbRefCStr = p2cstr( usbInterfaceRefStr);
- else if (theType == kUSBDeviceType)
- usbRefCStr = p2cstr( usbDeviceRefStr);
-
- while ((err == noErr) && (done == false))
- {
- theSize = sizeof(usbNodeType);
- err = RegistryPropertyGet(theEntry, usbNodeCStr, &usbNodeType, &theSize );
- if (err == noErr)
- {
- if (usbNodeType == theType)
- {
- theSize = sizeof(USBDeviceRef);
-
- err = RegistryPropertyGet(theEntry, usbRefCStr, &tempRef, &theSize);
- if ((err == noErr) && tempRef == ref)
- {
- found = true;
- break;
- }
- }
-
- err = RegistryEntrySearch( &cookie, iterOp, theEntry, &done, usbNodeCStr, nil, 0);
- }
- else
- USBExpertStatus(ref, "\pFindMatchingRegEntryForUSBRef: error calling RegistryPropertyGet", err);
-
-
- }
-
- RegistryEntryIterateDispose( &cookie );
-
- if (found == false)
- err = nrNotFoundErr;
-
- return err;
-
- }
-
-